package com.ozner.WaterPurifier.RoWifi;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.ozner.WaterPurifier.WaterPurifier;
import com.ozner.device.BaseDeviceIO;
import com.ozner.device.OperateCallback;
import com.ozner.util.ByteUtil;
import com.ozner.util.Convert;
import com.ozner.util.Helper;
import com.ozner.wifi.mxchip.Fog2.FogIO;
import com.ozner.wifi.mxchip.Pair.CRC8;

/**
 * Created by ozner_67 on 2017/8/1.
 * 邮箱：xinde.zhang@cftcn.com
 */

public class WaterPurifier_RO_WIFI extends WaterPurifier {
    private static final String TAG = "WaterPurifier_RO_WIFI";
    protected static final byte GroupCode_DeviceToApp = (byte) 0xFB;
    protected static final byte GroupCode_AppToDevice = (byte) 0xFA;
    protected static final byte GroupCode_DevceToServer = (byte) 0xFC;

    protected static final byte Opcode_RequestStatus = (byte) 0x01;
    protected static final byte Opcode_RespondStatus = (byte) 0x01;
    protected static final byte Opcode_ChangeStatus = (byte) 0x02;
    protected static final byte Opcode_DeviceInfo = (byte) 0x03;

    private RoWifiDeviceInfo deviceInfo;
    private RoWifiStatus wifiStatus;
    final WaterPurifierWiFiImp wiFiImp = new WaterPurifierWiFiImp();

    public WaterPurifier_RO_WIFI(Context context, String Address, String Type, String Setting) {
        super(context, Address, Type, Setting);
        deviceInfo = new RoWifiDeviceInfo();
        wifiStatus = new RoWifiStatus();
    }

//    @Override
//    protected String getDefaultName() {
//        return "厨下式水芯片（wifi版）";
//    }

    @Override
    public int getTimerDelay() {
        return super.getTimerDelay();
    }

    public RoWifiStatus roWifiStatus() {
        return wifiStatus;
    }

    public RoWifiDeviceInfo deviceInfo() {
        return deviceInfo;
    }

    @Override
    protected void doSetDeviceIO(BaseDeviceIO oldIO, BaseDeviceIO newIO) {
        if (oldIO != null) {
            oldIO.setOnTransmissionsCallback(null);
            oldIO.unRegisterStatusCallback(wiFiImp);
            oldIO.setOnInitCallback(null);
        }
        if (newIO != null) {
            FogIO io = (FogIO) newIO;
//            io.setSecureCode(SecureCode);
            io.setOnTransmissionsCallback(wiFiImp);
            io.registerStatusCallback(wiFiImp);
            io.setOnInitCallback(wiFiImp);
        }
        super.doSetDeviceIO(oldIO, newIO);
    }

    int requestCount = 0;

    @Override
    protected void updateStatus(final OperateCallback<Void> cb) {
        try {
            if (IO() == null) {
                if (cb != null) {
                    cb.onFailure(null);
                }
            } else {
                requestCount++;
                if (requestCount >= 3) {
                    setOffline(true);
                }

                IO().send(MakeWoodyBytes(GroupCode_AppToDevice, Opcode_RequestStatus, Address(), null), cb);
                Thread.sleep(100);
                IO().send(MakeWoodyBytes(GroupCode_AppToDevice, Opcode_DeviceInfo, Address(), null), cb);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
//            Log.e(TAG, "updateStatus_Ex: " + ex.getMessage());
        }
    }

    @Override
    protected int getTDS1() {
        return wifiStatus.TDS1;
    }

    @Override
    protected int getTDS2() {
        return wifiStatus.TDS2;
    }

    @Override
    protected int getTemperature() {
        return 0;
    }

    @Override
    protected boolean getSterilization() {
        return wifiStatus.Sterilization;
    }

    /**
     * 设置杀菌
     *
     * @param Sterilization
     * @param cb
     */
    @Override
    public void setSterilization(boolean Sterilization, final OperateCallback<Void> cb) {
        if (connectStatus() != BaseDeviceIO.ConnectStatus.Connected) {
            if (cb != null) {
                cb.onFailure(null);
            }
            return;
        }
        byte[] payload = new byte[4];
        payload[3] = Sterilization ? (byte) 0x01 : (byte) 0x00;
        byte[] data = MakeWoodyBytes(GroupCode_AppToDevice, Opcode_ChangeStatus, Address(), payload);
        Log.e(TAG, "设置杀菌: " + Convert.ByteArrayToHexString(data));
        IO().send(data, new OperateCallback<Void>() {
            @Override
            public void onSuccess(Void var1) {
                if (cb != null) {
                    cb.onSuccess(var1);
                }
                updateStatus(null);
                Log.e(TAG, "onSuccess: 修改属性完成");
            }

            @Override
            public void onFailure(Throwable var1) {
                if (cb != null) {
                    cb.onFailure(var1);
                }
                updateStatus(null);
                Log.e(TAG, "onFailure: 修改属性失败");
            }
        });
    }

    @Override
    public Class<?> getIOType() {
        return FogIO.class;
    }

    public static byte[] MakeWoodyBytes(byte Group, byte OpCode, String Address, byte[] payload) {
        int len = 10 + (payload == null ? 3 : payload.length + 3);
        byte[] bytes = new byte[len];
        bytes[0] = Group;
        ByteUtil.putShort(bytes, (short) len, 1);
        bytes[3] = OpCode;

        byte[] macs = Helper.HexString2Bytes(Address.replace(":", ""));
        System.arraycopy(macs, 0, bytes, 4, 6);

        bytes[10] = 0;//保留数据
        bytes[11] = 0;//保留数据
        if (payload != null)
            System.arraycopy(payload, 0, bytes, 12, payload.length);

        bytes[len - 1] = CRC8.calcCrc8(bytes, 0, bytes.length - 1);
        return bytes;
    }


    class WaterPurifierWiFiImp implements
            BaseDeviceIO.OnTransmissionsCallback,
            BaseDeviceIO.StatusCallback,
            BaseDeviceIO.OnInitCallback {

        @Override
        public void onConnected(BaseDeviceIO io) {

        }

        @Override
        public void onDisconnected(BaseDeviceIO io) {

        }

        @Override
        public void onReady(BaseDeviceIO io) {
            updateStatus(null);
        }

        @Override
        public void onIOSend(byte[] bytes) {

        }

        @Override
        public void onIORecv(byte[] data) {
            String dataStr = new String(data);
            Log.e(TAG, "onIORecv: " + dataStr);
            byte[] bytes = Convert.StringToByteArray(dataStr);
            if ((bytes == null) || (bytes.length <= 0)) {
                return;
            }

            if (isOffline) {
                setOffline(false);
            }

            requestCount = 0;
            if ((bytes != null) && (bytes.length > 10)) {
                byte group = bytes[0];
                byte opCode = bytes[3];
                switch (group) {
                    case GroupCode_DeviceToApp:
                        switch (opCode) {
                            case Opcode_RespondStatus:
                                requestCount = 0;
                                wifiStatus.fromBytes(bytes);
                                Log.e(TAG, "onIORecv: wifiStatus:" + wifiStatus.toString());
                                Intent intent = new Intent(ACTION_WATER_PURIFIER_STATUS_CHANGE);
                                intent.putExtra(Extra_Address, Address());
                                context().sendBroadcast(intent);
                                isOffline = false;
                                break;
                            case Opcode_DeviceInfo:
                                deviceInfo.fromBytes(bytes);
                                Log.e(TAG, "onIORecv: DeviceInfo:" + deviceInfo.toString());
                                setObject();
                                isOffline = false;
                                break;
                        }
                        break;
                }

            }
        }

        @Override
        public boolean onIOInit() {
            try {
                isOffline = true;
                IO().send(MakeWoodyBytes(GroupCode_AppToDevice, Opcode_RequestStatus, Address(), null), null);
                Thread.sleep(100);
                IO().send(MakeWoodyBytes(GroupCode_AppToDevice, Opcode_DeviceInfo, Address(), null), null);
                waitObject(5000);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    }


}
